/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-12-10     Administrator       the first version
 */
#ifndef APPLICATIONS_SPI_SH1106_OLED_SH1106_C_
#define APPLICATIONS_SPI_SH1106_OLED_SH1106_C_

#include "oled_sh1106.h"
#include "oled_font.h"
#include "stdlib.h"
#include "delay.h"
#include <rtthread.h>
#include "board.h"
#define SIZE 16
#define Max_Column  128
extern char adc_flag;
extern char Function;
//反显函数
void OLED_ColorTurn(uint8_t i)
{
    if(i==0)
    {
        OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
    }
    if(i==1)
    {
        OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
    }
}

//屏幕旋转180度
void OLED_DisplayTurn(uint8_t i)
{
    if(i==0)
    {
        OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
        OLED_WR_Byte(0xA1,OLED_CMD);
    }
    if(i==1)
    {
        OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
        OLED_WR_Byte(0xA0,OLED_CMD);
    }
}

//开启OLED显示
void OLED_DisPlay_On(void)
{
    OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
    OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
    OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}

//关闭OLED显示
void OLED_DisPlay_Off(void)
{
    OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
    OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
    OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
}


//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{
    uint8_t i;
    uint8_t SCL= rt_pin_get("PE.3");
    rt_pin_mode(SCL, PIN_MODE_OUTPUT);
    rt_pin_write(SCL, PIN_HIGH);

    uint8_t SDA = rt_pin_get("PE.2");
    rt_pin_mode(SDA, PIN_MODE_OUTPUT);
    rt_pin_write(SDA, PIN_HIGH);

    uint8_t DC = rt_pin_get("PA.0");
    rt_pin_mode(DC, PIN_MODE_OUTPUT);
    rt_pin_write(DC, PIN_HIGH);

    uint8_t CS = rt_pin_get("PA.2");
    rt_pin_mode(CS, PIN_MODE_OUTPUT);
    rt_pin_write(CS, PIN_HIGH);
    if(cmd)
        rt_pin_write(DC, PIN_HIGH);
    else
        rt_pin_write(DC, PIN_LOW);
    rt_pin_write(CS, PIN_LOW);
    for(i=0;i<8;i++)
    {
        rt_pin_write(SCL, PIN_LOW);
        if(dat&0x80)
            rt_pin_write(SDA, PIN_HIGH);
        else
            rt_pin_write(SDA, PIN_LOW);
        rt_pin_write(SCL, PIN_HIGH);
        dat<<=1;
    }
    rt_pin_write(CS, PIN_HIGH);
    rt_pin_write(DC, PIN_HIGH);
}

//清屏函数
void OLED_Clear(void)
{
    uint8_t i,n;
    for(i=0;i<8;i++)
    {
         OLED_WR_Byte(0xb0+i,OLED_CMD);//设置页地址
       OLED_WR_Byte(0x10,OLED_CMD);  //设置列地址的高4位
       OLED_WR_Byte(0x02,OLED_CMD);  //设置列地址的低4位
       for(n=0;n<128;n++)
         {
             OLED_WR_Byte(0x00,OLED_DATA);//清除所有数据
         }
  }
}

//设置起始地址
void OLED_address(uint8_t x,uint8_t y)
{
    x+=2;
    OLED_WR_Byte(0xb0+y,OLED_CMD);              //设置页地址
    OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);  //设置列地址的高4位
    OLED_WR_Byte((x&0x0f),OLED_CMD);            //设置列地址的低4位
}

//显示128x64点阵图像
void OLED_Display_128x64(uint8_t *dp)
{
    uint8_t i,j;
    for(i=0;i<8;i++)
    {
        OLED_address(0,i);
        for(j=0;j<128;j++)
        {
            OLED_WR_Byte(*dp,OLED_DATA); //写数据到OLED,每写完一个8位的数据后列地址自动加1
            dp++;
    }
  }
}

//显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标
void OLED_Display_16x16(uint8_t x,uint8_t y,uint8_t *dp)
{
    uint8_t i,j;
    for(j=0;j<2;j++)
    {
        OLED_address(x,y);
        for(i=0;i<16;i++)
        {
            OLED_WR_Byte(*dp,OLED_DATA);  //写数据到OLED,每写完一个8位的数据后列地址自动加1
            dp++;
    }
        y++;
  }
}

//显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标
void OLED_Display_8x16(uint8_t x,uint8_t y,uint8_t *dp)
{
    uint8_t i,j;
    for(j=0;j<2;j++)
    {
        OLED_address(x,y);
        for(i=0;i<8;i++)
        {
            OLED_WR_Byte(*dp,OLED_DATA);   //写数据到LCD,每写完一个8位的数据后列地址自动加1
            dp++;
    }
        y++;
  }
}

//显示5*7点阵图像、ASCII, 或5x7点阵的自造字符、其他图标
void OLED_Display_5x7(uint8_t x,uint8_t y,uint8_t *dp)
{
    uint8_t i;
  OLED_address(x,y);
    for(i=0;i<6;i++)
    {
        OLED_WR_Byte(*dp,OLED_DATA);
        dp++;
  }
}

void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD);
}

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr)
{
    unsigned char c=0,i=0;
        c=chr-' ';//得到偏移后的值
        if(x>Max_Column-1){x=0;y=y+2;}
        if(SIZE ==16)
            {
            OLED_Set_Pos(x,y);
            for(i=0;i<8;i++)
            OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
            OLED_Set_Pos(x,y+1);
            for(i=0;i<8;i++)
            OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
            }
            else {
                OLED_Set_Pos(x,y+1);
                for(i=0;i<6;i++)
                OLED_WR_Byte(F6x8[c][i],OLED_DATA);

            }
}
//m^n函数
uint32_t oled_pow(uint8_t m,uint8_t n)
{
    uint32_t result=1;
    while(n--)result*=m;
    return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式   0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{
    uint8_t t,temp;
    uint8_t enshow=0;
    for(t=0;t<len;t++)
    {
        temp=(num/oled_pow(10,len-t-1))%10;
        if(enshow==0&&t<(len-1))
        {
            if(temp==0)
            {
                OLED_ShowChar(x+(size/2)*t,y,' ');
                continue;
            }else enshow=1;

        }
        OLED_ShowChar(x+(size/2)*t,y,temp+'0');
    }
}
//显示一个字符号串
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr)
{
    unsigned char j=0;
    while (chr[j]!='\0')
    {       OLED_ShowChar(x,y,chr[j]);
            x+=8;
        if(x>120){x=0;y+=2;}
            j++;
    }
}
//显示汉字
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
    uint8_t t,adder=0;
    OLED_Set_Pos(x,y);
    for(t=0;t<16;t++)
        {
                OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
                adder+=1;
     }
        OLED_Set_Pos(x,y+1);
    for(t=0;t<16;t++)
            {
                OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
                adder+=1;
      }
}
//OLED的初始化
void OLED_Init(void)
{
    uint8_t pin = rt_pin_get("PE.3");
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_pin_write(pin, PIN_HIGH);

     pin = rt_pin_get("PE.2");
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_pin_write(pin, PIN_HIGH);

     pin = rt_pin_get("PA.0");
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_pin_write(pin, PIN_HIGH);

     pin = rt_pin_get("PA.2");
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_pin_write(pin, PIN_HIGH);

     pin = rt_pin_get("PA.1");
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_pin_write(pin, PIN_HIGH);


    rt_thread_mdelay(200);

    OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/
    OLED_WR_Byte(0x02,OLED_CMD); /*set lower column address*/
    OLED_WR_Byte(0x10,OLED_CMD); /*set higher column address*/
    OLED_WR_Byte(0x40,OLED_CMD); /*set display start line*/
    OLED_WR_Byte(0xB0,OLED_CMD); /*set page address*/
    OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/
    OLED_WR_Byte(0xcf,OLED_CMD); /*128*/
    OLED_WR_Byte(0xA1,OLED_CMD); /*set segment remap*/
    OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/
    OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/
    OLED_WR_Byte(0x3F,OLED_CMD); /*duty = 1/64*/
    OLED_WR_Byte(0xad,OLED_CMD); /*set charge pump enable*/
    OLED_WR_Byte(0x8b,OLED_CMD); /* 0x8B 内供 VCC */
    OLED_WR_Byte(0x33,OLED_CMD); /*0X30---0X33 set VPP 9V */
    OLED_WR_Byte(0xC8,OLED_CMD); /*Com scan direction*/
    OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
    OLED_WR_Byte(0x00,OLED_CMD); /* 0x20 */
    OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/
    OLED_WR_Byte(0x80,OLED_CMD);
    OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/
    OLED_WR_Byte(0x1f,OLED_CMD); /*0x22*/
    OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/
    OLED_WR_Byte(0x12,OLED_CMD);
    OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/
    OLED_WR_Byte(0x40,OLED_CMD);
    OLED_Clear();
    OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
}

static int oled_sample(int argc, char *argv[])
{
    OLED_Init();
    OLED_Clear();
    rt_thread_mdelay(2000);
    OLED_ShowString(11, 11, "abdc");
    OLED_ShowChar(21, 3, 'a');
    OLED_ShowCHinese(92, 6, 9);
}
MSH_CMD_EXPORT(oled_sample, oled sample 11);
static void oled_thread_entry(void* p)
{
    OLED_Init();
    OLED_Clear();
    rt_thread_mdelay(2000);
 while(1)
 {
    if(Function==1)
    {
        rt_enter_critical();
        OLED_ShowCHinese(10, 2, 2);
        OLED_ShowCHinese(26, 2, 3);
        OLED_ShowCHinese(42, 2, 4);
        OLED_ShowCHinese(58, 2, 5);
        OLED_ShowCHinese(74, 2, 6);
        rt_exit_critical();
        if(adc_flag==1)
        {OLED_ShowCHinese(42, 5, 1);}
        else {
            OLED_ShowCHinese(42, 5, 9);
        }
    }
    if(Function==2)
    {
        rt_enter_critical();
        OLED_ShowCHinese(10, 2, 2);
        OLED_ShowCHinese(26, 2, 7);
        OLED_ShowCHinese(42, 2, 8);
        OLED_ShowCHinese(58, 2, 5);
        OLED_ShowCHinese(74, 2, 6);
        OLED_ShowCHinese(42, 5, 9);
        rt_exit_critical();
    }
    rt_thread_mdelay(1000);
 }
}

static int Thread_oled(void)
{
 rt_thread_t thread = RT_NULL;
 thread = rt_thread_create("oled", oled_thread_entry, RT_NULL, 512, 10, 10);
 if(thread == RT_NULL)
 {
 rt_kprintf("Thread_OLED Init ERROR");
 return RT_ERROR;
 }
 rt_thread_startup(thread);
}
INIT_APP_EXPORT(Thread_oled);

#endif /* APPLICATIONS_SPI_SH1106_OLED_SH1106_C_ */
